﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

namespace Sistema.DAO.Nhibernate
{
    /// <summary>
    /// Classe responsavel por encapsular a sessao do nhibernate.
    /// </summary>
    static class NhibernateSession
    {
        private static readonly ISessionFactory sessionFactory;
        private static ISession currentSession;

        static NhibernateSession()
        {
            try
            {
                System.Configuration.AppSettingsReader config = new System.Configuration.AppSettingsReader();
                String Server = config.GetValue("Servidor", typeof(String)).ToString();
                String Porta = config.GetValue("Porta", typeof(String)).ToString();
                Configuration cfg = new Configuration();
                cfg.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
                cfg.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlAuto, "update");
                cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.MySqlDataDriver");
                cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionString, String.Format("Database=NFE;Data Source={0};User Id=sistema;Password=ns2008;Port={1}",Server,Porta));
                cfg.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.MySQLDialect");
                cfg.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle");
                cfg.SetProperty(NHibernate.Cfg.Environment.UseProxyValidator, "false");
                cfg.AddAssembly("Sistema.Dominio");

                sessionFactory = cfg.BuildSessionFactory();
                SchemaUpdate update = new SchemaUpdate(cfg);
                update.Execute(true, true);
            }
            catch (Exception ex)
            {
                throw new NHibernateException(String.Format(Properties.Resources.NhibernateExceptionMensagemErro, "NhibernateSession.Constructor", ex.Message),
                    "Houve um erro ao estabelecer coneccao com o banco de dados", ex);
            }
        }

        /// <summary>
        /// Retornar uma sessao para criar transacoes , comandos e o que mais desejar.
        /// </summary>
        /// <exception cref="NHibernateException">caso aconteca um erro na criacao da sessao pelo Nhibernate</exception>
        /// <returns>Retorna uma instancia do subtipo ISession.</returns>
        public static ISession GetCurrentSession()
        {
            try
            {
                if (currentSession == null)
                {
                    currentSession = sessionFactory.OpenSession();
                }
            }
            catch (Exception ex)
            {
                throw new NHibernateException(String.Format(Properties.Resources.NhibernateExceptionMensagemErro, "NhiebernateSession.getCurrentSession()", ex.Message),
                    "Houve um erro ao estabelecer uma sessao com o banco de dados.", ex);
            }
            return currentSession;
        }

        /// <summary>
        /// Fecha a sessao principal do nhiberante e suas dependencias.
        /// </summary>
        /// <exception cref="NhibernateException">Caso aconteca algum erro nesta operacao.</exception>
        public static void CloseSession()
        {
            try
            {
                if (currentSession == null) { return; }
                currentSession.Close();
                currentSession = null;

            }
            catch (Exception ex)
            {
                throw new NHibernateException(String.Format(Properties.Resources.NhibernateExceptionMensagemErro, "NhibernateSession.CloseSession()", ex.Message),
                    "Houve um erro ao fechar uma sessao com o banco de dados.", ex);
            }
        }

        /// <summary>
        /// Fechar a sessao criada pelo metodo GetCurrentSession
        /// </summary>
        /// <exception cref="NHibernateException">Caso aconteca um erro ao fechar a sessao com o nhibernate.</exception>
        public static void CloseCurrentSession()
        {
            try
            {
                CloseSession();
                if (sessionFactory != null)
                {
                    sessionFactory.Close();
                }
            }
            catch (Exception ex)
            {
                throw new NHibernateException(String.Format(Properties.Resources.NhibernateExceptionMensagemErro, "NhibernateSession.CloseSession()", ex.Message),
                    "houve um erro ao fechar a sessao com o banco de dados", ex);
            }
        }
    }
}
